package com.iplant.base.utils.general;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.iplant.base.utils.serializer.CloneTool;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.security.MessageDigest;
import java.text.MessageFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 工具类 可置于service中
 *
 * @author ShrisJava
 */
public class StringUtils {
    private static Logger logger = LoggerFactory.getLogger(StringUtils.class);

    private static Map<String, MessageDigest> digests = new ConcurrentHashMap<String, MessageDigest>();

    public static Integer parseInt(Object value) {

        return parseInt(value, 0);
    }

    public static Integer parseInt(Object value, int defaultValue) {
        if (value != null && StringUtils.isNotEmpty(value.toString())) {

            if (value instanceof Integer) {
                return (Integer) value;
            } else if (value instanceof Float) {
                return ((Float) value).intValue();
            } else if (value instanceof Double) {
                return ((Double) value).intValue();
            } else if (value instanceof Boolean) {
                return ((Boolean) value) ? 1 : 0;
            } else {

                if ("true".equalsIgnoreCase(value.toString())) {
                    return 1;
                } else if ("else".equalsIgnoreCase(value.toString())) {
                    return 0;
                }
                try {
                    return Integer.parseInt(value.toString());
                } catch (Exception e) {
                    return defaultValue;
                }
            }
        }
        return defaultValue;
    }

    public static Short parseShort(Object value) {
        if (value != null && StringUtils.isNotEmpty(value.toString())) {
            if (value instanceof Short) {
                return (Short) value;
            } else {
                try {
                    return Short.valueOf(value.toString());
                } catch (Exception e) {
                    return 0;
                }
            }
        }
        return 0;
    }

    public static Byte parseByte(Object value) {
        if (value != null && StringUtils.isNotEmpty(value.toString())) {
            if (value instanceof Byte) {
                return (Byte) value;
            } else {
                try {
                    return Byte.valueOf(value.toString());
                } catch (Exception e) {
                    return 0;
                }
            }
        }
        return 0;
    }

    public static Float parseFloat(Object value) {
        if (value != null && StringUtils.isNotEmpty(value.toString())) {
            if (value instanceof Float) {
                return (Float) value;
            } else if (value instanceof Integer) {
                return ((Integer) value).floatValue();
            } else if (value instanceof Short) {
                return ((Short) value).floatValue();
            } else if (value instanceof Byte) {
                return ((Byte) value).floatValue();
            } else if (value instanceof Double) {
                return ((Double) value).floatValue();
            } else {
                try {
                    return Float.valueOf(value.toString());
                } catch (Exception e) {
                    return 0f;
                }
            }
        }
        return 0f;
    }

    public static Long parseLong(Object value) {
        if (value != null && StringUtils.isNotEmpty(value.toString())) {
            if (value instanceof Long) {
                return (Long) value;
            }
            if (value instanceof Integer) {
                return ((Integer) value).longValue();
            } else {
                try {
                    return Long.valueOf(value.toString());
                } catch (Exception ex) {
                    return 0L;
                }
            }
        }
        return 0L;
    }

    public static Double parseDouble(Object value, Double defaultValue) {
        if (value != null && StringUtils.isNotEmpty(value.toString())) {
            if (value instanceof Double) {
                return (Double) value;
            }
            if (value instanceof BigDecimal) {
                return ((BigDecimal) value).doubleValue();
            }
            if (value instanceof Integer) {
                return ((Integer) value).doubleValue();
            } else if (value instanceof Float) {
                return ((Float) value).doubleValue();
            } else if (value instanceof String) {
                try {
                    return Double.valueOf((String) value);
                } catch (Exception ex) {
                    return defaultValue;
                }
            }
        }
        return defaultValue;
    }

    public static Double parseDouble(Object value) {
        return parseDouble(value, 0.0);
    }

    public static String parseString(Object value) {
        if (value != null) {

            if (Calendar.class.isInstance(value)) {
                return parseCalendarToString((Calendar) value, "yyyy-MM-dd HH:mm:ss");
            } else if (Date.class.isInstance(value)) {
                return parseDateToString((Date) value, "yyyy-MM-dd HH:mm:ss");
            } else if (Float.class.isInstance(value) || Double.class.isInstance(value)) {

                BigDecimal bd = new BigDecimal(value.toString());

                String formattedNumber = bd.toPlainString();
//                if (formattedNumber.contains(".") && formattedNumber.endsWith("0")) {
//                    formattedNumber = formattedNumber.substring(0, formattedNumber.length() - 1);
//                }
                return formattedNumber;
            }
            return String.valueOf(value);
        }
        return "";
    }

    public static String parseString(Object value, String wFormat) {
        if (value != null) {

            if (Calendar.class.isInstance(value)) {
                return parseCalendarToString((Calendar) value, wFormat);
            } else if (Date.class.isInstance(value)) {
                return parseDateToString((Date) value, wFormat);
            } else if (Float.class.isInstance(value)) {
                return value.toString();
            } else if (Double.class.isInstance(value)) {
                return value.toString();
            }
            return String.valueOf(value);
        }
        return "";
    }

    public static <T> List<T> parseList(Object value, Class<T> calzz) {
        if (value != null) {
            try {
                value = CloneTool.CloneArray(value, calzz);
            } catch (Exception ex) {
                return null;
            }
        }
        return null;
    }

    @SafeVarargs
    public static <T> List<T> parseListArgs(T... value) {
        List<T> wResult = new ArrayList<T>();
        if (value != null) {
            try {
                for (T t : value) {
                    if (t == null) {
                        continue;
                    }

                    if ((t instanceof String) && isEmpty(t.toString())) {
                        continue;
                    }
                    wResult.add(t);
                }
            } catch (Exception ex) {
                return wResult;
            }

        }
        return wResult;
    }

    public static <T> List<T> parseList(T[] value) {
        List<T> wResult = new ArrayList<T>();
        if (value != null) {
            try {
                for (T t : value) {
                    if (t == null) {
                        continue;
                    }

                    if ((t instanceof String) && isEmpty(t.toString())) {
                        continue;
                    }
                    wResult.add(t);
                }
            } catch (Exception ex) {
                return wResult;
            }

        }
        return wResult;
    }

    public static Integer[] parseIntArray(List<String> value) {

        Integer[] wResult = new Integer[0];
        wResult = parseIntList(value).toArray(wResult);
        return wResult;
    }

    public static Integer[] parseIntArray(String[] value) {

        Integer[] wResult = new Integer[0];
        wResult = parseIntList(value).toArray(wResult);
        return wResult;
    }

    public static List<Integer> parseIntList(List<String> value) {

        List<Integer> wResult = new ArrayList<Integer>();
        if (value != null) {
            int wInt = 0;
            try {
                for (int i = 0; i < value.size(); i++) {
                    if (StringUtils.isEmpty(value.get(i))) {
                        continue;
                    }

                    wInt = StringUtils.parseInt(value.get(i));
                    if (wResult.contains(wInt)) {
                        continue;
                    }
                    wResult.add(wInt);
                }
            } catch (Exception ex) {
                return wResult;
            }
        }
        return wResult;
    }

    public static List<Integer> parseIntList(String[] value) {

        List<Integer> wResult = new ArrayList<Integer>();
        if (value != null) {
            int wInt = 0;
            try {
                for (int i = 0; i < value.length; i++) {

                    if (StringUtils.isEmpty(value[i])) {
                        continue;
                    }

                    wInt = StringUtils.parseInt(value[i]);
                    if (wResult.contains(wInt)) {
                        continue;
                    }
                    wResult.add(wInt);
                }
            } catch (Exception ex) {
                return wResult;
            }
        }
        return wResult;
    }

    public static Long[] parseLongArray(List<String> value) {

        Long[] wResult = new Long[0];
        wResult = parseLongList(value).toArray(wResult);
        return wResult;
    }

    public static Long[] parseLongArray(String[] value) {

        Long[] wResult = new Long[0];

        wResult = parseLongList(value).toArray(wResult);

        return wResult;
    }

    public static List<Long> parseLongList(List<String> value) {

        List<Long> wResult = new ArrayList<Long>();
        if (value != null) {
            long wLong = 0;
            try {
                for (int i = 0; i < value.size(); i++) {

                    if (StringUtils.isEmpty(value.get(i))) {
                        continue;
                    }

                    wLong = StringUtils.parseLong(value.get(i));
                    if (wResult.contains(wLong)) {
                        continue;
                    }

                    wResult.add(wLong);
                }
            } catch (Exception ex) {
                return wResult;
            }
        }
        return wResult;
    }

    public static List<Long> parseLongList(String[] value) {

        List<Long> wResult = new ArrayList<Long>();
        if (value != null) {
            long wLong = 0;
            try {
                for (int i = 0; i < value.length; i++) {
                    if (StringUtils.isEmpty(value[i])) {
                        continue;
                    }

                    wLong = StringUtils.parseLong(value[i]);
                    if (wResult.contains(wLong)) {
                        continue;
                    }

                    wResult.add(wLong);
                }
            } catch (Exception ex) {
                return wResult;
            }
        }
        return wResult;
    }

    public static List<Double> parseDoubleList(String[] value) {

        List<Double> wResult = new ArrayList<Double>();
        if (value != null) {
            Double wInt = 0.0;
            try {
                for (int i = 0; i < value.length; i++) {
                    if (StringUtils.isEmpty(value[i])) {
                        continue;
                    }

                    wInt = StringUtils.parseDouble(value[i]);
                    if (wResult.contains(wInt)) {
                        continue;
                    }
                    wResult.add(wInt);
                }
            } catch (Exception ex) {
                return wResult;
            }
        }
        return wResult;
    }

    public static Boolean parseBoolean(Object value) {
        if (value != null) {
            if (value instanceof Integer) {
                return ((Integer) value).intValue() == 1;
            } else if (value instanceof String) {
                return "1".equals(value) || "true".equalsIgnoreCase(value.toString());
            } else if (value instanceof Boolean) {
                return (Boolean) value;
            }
        }
        return false;
    }

    public static String hash(String data) {
        return hash(data, "MD5");
    }

    public static String hash(String data, String algorithm) {
        try {
            return hash(data.getBytes("utf-8"), algorithm);
        } catch (UnsupportedEncodingException e) {

        }
        return data;
    }

    public static String hash(byte[] bytes, String algorithm) {
        synchronized (algorithm.intern()) {
            MessageDigest digest = digests.get(algorithm);
            if (digest == null) {
                try {
                    digest = MessageDigest.getInstance(algorithm);
                    digests.put(algorithm, digest);
                } catch (Exception nsae) {
                    return null;
                }
            }
            // Now, compute hash.
            digest.update(bytes);
            return encodeHex(digest.digest());
        }
    }

    public static String encodeHex(byte[] bytes) {
        StringBuilder buf = new StringBuilder(bytes.length * 2);
        int i;

        for (i = 0; i < bytes.length; i++) {
            if (((int) bytes[i] & 0xff) < 0x10) {
                buf.append("0");
            }
            buf.append(Long.toString((int) bytes[i] & 0xff, 16));
        }
        return buf.toString();
    }

    /**
     * 判断是否时空对象  数字<0是空 String empty是空  date<2010年是空
     *
     * @param wObject
     * @return
     */
    public static boolean IsEmptyCondition(Object wObject) {
        if (wObject == null) {
            return true;
        }
        if (wObject instanceof Date) {
            if (((Date) wObject).compareTo(CalendarTool.getUsedDate().getTime()) <= 0) {
                return true;
            }
        }
        if (wObject instanceof Calendar) {
            if (((Calendar) wObject).compareTo(CalendarTool.getUsedDate()) <= 0) {
                return true;
            }
        }
        if (wObject instanceof Number) {
            if (((Number) wObject).doubleValue() < 0) {
                return true;
            }
        }

        //暂不支持集合处理  TODO: 2022/11/18
        if (wObject instanceof Collection) {

        }
        if (wObject instanceof Map) {

        }
        if (wObject instanceof Array) {

        }

        return false;
    }

    public static boolean isEmpty(String str) {
        return str == null || str.trim().length() == 0;
    }


    public static boolean isNotEmpty(String str) {
        return !StringUtils.isEmpty(str);
    }

    public static String trim(String str) {
        return str == null ? null : str.trim();
    }

    /**
     * 计算字符串字节长度
     *
     * @param str
     * @return
     * @author Femi
     */
    public static int getStringByteLength(String str) {
        char[] t = str.toCharArray();
        int count = 0;
        for (char c : t) {
            if ((c >= 0x4e00) && (c <= 0x9fbb)) {
                count = count + 2;
            } else {
                count++;
            }
        }
        return count;
    }

    public static String parseInputStreamToString(InputStream is) {
        BufferedReader reader = new BufferedReader(new InputStreamReader(is));
        StringBuilder sb = new StringBuilder();

        String line = null;
        try {
            while ((line = reader.readLine()) != null) {
                sb.append(line);
            }
        } catch (IOException e) {
        } finally {
            try {
                is.close();
                is = null;
            } catch (IOException e) {
            }
        }
        return sb.toString();

    }

    public static Date parseDate(String value, String format) {

        try {
            format = format.replaceAll("T", "'T'").replaceAll("''T''", "'T'");
            format = format.replaceAll("Z", "'Z'").replaceAll("''Z''", "'Z'");
            SimpleDateFormat DateFormat = new SimpleDateFormat(format);
            if (format.contains("T")) {
                DateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
            }
            return DateFormat.parse(value);
        } catch (ParseException e) {
            // TODO Auto-generated catch block
            logger.error(e.getMessage());
        }
        return null;
    }

    public static Calendar FormatCalendar(Calendar value, String format) {
        Calendar wResult = Calendar.getInstance();
        wResult.set(2000, 0, 1);
        try {
            SimpleDateFormat DateFormat = new SimpleDateFormat(format);

            wResult.setTime(DateFormat.parse(DateFormat.format(value.getTime())));
        } catch (Exception e) {
            logger.error(e.getMessage());
        }

        return wResult;
    }

    public static Calendar parseCalendar(Object value, String format) {
        Calendar wCalendar = Calendar.getInstance();
        try {
            wCalendar.set(1970, 0, 1);

            if (value == null || StringUtils.isEmpty(value.toString())) {
                return wCalendar;
            }

            if (value instanceof Calendar) {
                wCalendar = (Calendar) value;
            } else if (value instanceof Date) {
                wCalendar.setTime((Date) value);
            } else if (value instanceof Long) {
                wCalendar.setTimeInMillis((long) value);
            } else if (value instanceof Integer) {
                wCalendar.add(Calendar.MILLISECOND, (int) value);
            } else if (value instanceof String) {

                format = format.replaceAll("T", "'T'").replaceAll("''T''", "'T'");
                format = format.replaceAll("Z", "'Z'").replaceAll("''Z''", "'Z'");
                SimpleDateFormat DateFormat = new SimpleDateFormat(format);
                if (format.contains("'T'")) {
                    DateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
                }
                wCalendar.setTime(DateFormat.parse((String) value));
            } else {
                format = format.replaceAll("T", "'T'").replaceAll("''T''", "'T'");
                format = format.replaceAll("Z", "'Z'").replaceAll("''Z''", "'Z'");
                SimpleDateFormat DateFormat = new SimpleDateFormat(format);
                if (format.contains("'T'")) {
                    DateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
                }
                wCalendar.setTime(DateFormat.parse(value.toString()));
            }
        } catch (ParseException e) {
            System.out.println("format:" + format + "  value:" + value.toString());
            logger.error(e.getMessage());
        }
        return wCalendar;
    }

    public static String DencodeURIComponent(String wValue, String wKey) {
        if (wValue == null || wValue.trim().isEmpty() || wKey == null || wKey.trim().isEmpty()) {
            return "";
        }

        if (!wValue.startsWith("?")) {
            wValue = "?" + wValue;
        }

        int wIndex = wValue.indexOf("?" + wKey + "=");
        if (wIndex < 0) {
            wIndex = wValue.indexOf("&" + wKey + "=");
        }

        if (wIndex < 0) {
            return "";
        }

        String wResut = wValue.substring(wIndex + 1);
        wIndex = wResut.indexOf('&');
        wResut = wResut.substring(wKey.length() + 1, wIndex);

        return wResut;
    }

    public static Calendar parseCalendar(Object value) {

        Calendar wResult = Calendar.getInstance();
        wResult.set(1970, 0, 1);
        try {

            if (value == null || StringUtils.isEmpty(value.toString())) {
                return wResult;
            }
            if ((value instanceof String) && value.toString().length() >= 4) {
                value = value.toString().trim();
                Matcher wMatcher = Pattern.compile(
                        "\\d{4}([\\-\\/])\\d{1,2}([\\-\\/])\\d{1,2}([T\\s])\\d{1,2}:\\d{1,2}:\\d{1,2}",
                        Pattern.CASE_INSENSITIVE).matcher(value.toString());

                if (wMatcher.find()) {
                    wResult = parseCalendar(wMatcher.group(0),
                            StringUtils.Format("yyyy{0}MM{1}dd{2}HH:mm:ss", wMatcher.group(1), wMatcher.group(2),
                                    wMatcher.group(3)));
                    return wResult;
                }

                wMatcher = Pattern.compile(
                        "\\d{4}([\\/\\-\\\\])\\d{1,2}([\\/\\-\\\\])\\d{1,2}([T\\s])\\d{1,2}:\\d{1,2}",
                        Pattern.CASE_INSENSITIVE).matcher(value.toString());

                if (wMatcher.find()) {
                    wResult = parseCalendar(wMatcher.group(0),
                            StringUtils.Format("yyyy{0}MM{1}dd{2}HH:mm", wMatcher.group(1), wMatcher.group(2),
                                    wMatcher.group(3)));
                    return wResult;
                }

                wMatcher = Pattern.compile("\\d{4}([\\-\\/])\\d{1,2}([\\-\\/])\\d{1,2}", Pattern.CASE_INSENSITIVE)
                        .matcher(value.toString());

                if (wMatcher.find()) {
                    wResult = parseCalendar(wMatcher.group(0),
                            StringUtils.Format("yyyy{0}MM{1}dd", wMatcher.group(1), wMatcher.group(2)));
                    return wResult;
                }

                wMatcher = Pattern.compile("\\d{1,2}:\\d{1,2}:\\d{1,2}", Pattern.CASE_INSENSITIVE).matcher(
                        value.toString());

                if (wMatcher.find()) {
                    wResult = parseCalendar(wMatcher.group(0), "HH:mm:ss");
                    return wResult;
                }

            } else {
                wResult = parseCalendar(value, "yyyy-MM-dd HH:mm:ss");
            }

        } catch (Exception e) {
            logger.error(e.getMessage());
        }

        return wResult;
    }

    public static String RepleaceRegx(String value, String wPat) {

        Matcher wMatcher = Pattern.compile(wPat, Pattern.CASE_INSENSITIVE).matcher(value);
        StringBuffer sb = new StringBuffer();
        while (wMatcher.find()) {
            wMatcher.appendReplacement(sb,
                    StringUtils.parseCalendarToString(StringUtils.parseCalendar(wMatcher.group(1)),
                            "yyyy-MM-dd HH:mm:ss"));

        }
        wMatcher.appendTail(sb);
        value = sb.toString();

        return value;
    }


    public static boolean isNumeric(String wValue) {
        boolean wResult = false;
        try {
            if (isEmpty(wValue)) {
                return wResult;
            }

            Double.parseDouble(wValue);
            wResult = true;
        } catch (Exception e) {
            wResult = false;
        }
        return wResult;
    }

    @SuppressWarnings("unchecked")
    public static <T> T CombineData(T wTask, Object wData) {

        try {
            if (wTask == null || wData == null) {
                return wTask;
            }
            Map<String, Object> wDataMap = CloneTool.Clone(wData, Map.class);

            Field[] fields = wTask.getClass().getFields();
            for (String wPropName : wDataMap.keySet()) {
                for (Field wField : fields) {
                    if (!wField.getName().equals(wPropName)) {
                        continue;
                    }

                    wField.set(wTask, CloneTool.Clone(wDataMap.get(wPropName), wField.getType()));
                }
            }
        } catch (Exception e) {
            logger.error(e.toString());
        }
        return wTask;
    }

    public static String CombinePath(String... value) {
        String wResult = "";
        if (value == null || value.length <= 0) {
            return wResult;
        }

        StringBuilder wStringBuilder = new StringBuilder();
        boolean wStartRemove = false;
        for (int i = 0; i < value.length; i++) {
            if (value[i] == null || value[i].trim().length() <= 0) {
                continue;
            }
            value[i] = value[i].trim();
            wStartRemove = false;

            if (value[i].startsWith("/") || value[i].startsWith("\\")) {
                value[i] = value[i].substring(1);
                wStartRemove = true;
            }
            if (value[i].startsWith("//") || value[i].startsWith("\\\\")) {
                value[i] = value[i].substring(2);
                wStartRemove = true;
            }
            if (i == 0 && wStartRemove) {
                value[i] = "/" + value[i];
            }

            wStartRemove = false;

            if (value[i].endsWith("/") || value[i].endsWith("\\")) {
                value[i] = value[i].substring(0, value[i].length() - 1);
                wStartRemove = true;
            }
            if (value[i].endsWith("//") || value[i].endsWith("\\\\")) {
                value[i] = value[i].substring(0, value[i].length() - 2);
                wStartRemove = true;
            }

            if (i != value.length - 1) {
                value[i] += "/";
            } else if (i == value.length - 1 && wStartRemove) {
                value[i] += "/";
            }

            wStringBuilder.append(value[i]);
        }
        wResult = wStringBuilder.toString();
        return wResult;
    }

    public static String parseDateToString(Date value, String format) {
        SimpleDateFormat DateFormat = new SimpleDateFormat(format);
        return DateFormat.format(value);
    }

    public static String parseCalendarToString(Calendar value, String format) {
        SimpleDateFormat DateFormat = new SimpleDateFormat(format);
        return DateFormat.format(value.getTime());
    }

    public static String toJSONString(Object value) {
        return JSON.toJSONStringWithDateFormat(value, "yyyy-MM-dd HH:mm:ss", SerializerFeature.WriteMapNullValue,
                SerializerFeature.WriteDateUseDateFormat, SerializerFeature.DisableCircularReferenceDetect);
    }

    public static String parseToCalendarString(Object value, String format) {
        SimpleDateFormat DateFormat = new SimpleDateFormat(format);
        return DateFormat.format(parseCalendar(value).getTime());
    }


    public static String CalendarFormat(Calendar value, String format) {
        SimpleDateFormat DateFormat = new SimpleDateFormat(format);
        return DateFormat.format(value.getTime());
    }

    public static String CalendarFormat(Calendar value) {
        SimpleDateFormat DateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return DateFormat.format(value.getTime());
    }

    public static String DateFormat(Date value) {
        SimpleDateFormat DateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return DateFormat.format(value);
    }

    public static String DateFormat(Date value, String format) {
        SimpleDateFormat DateFormat = new SimpleDateFormat(format);
        return DateFormat.format(value);
    }

    public static <T> String Join(String delimiter, Collection<T> wValues) {
        if (delimiter == null || wValues == null) {
            return "";
        }
        // Number of elements not likely worth Arrays.stream overhead.
        StringJoiner joiner = new StringJoiner(delimiter);
        for (T cs : wValues) {
            joiner.add(cs.toString());
        }
        return joiner.toString();

    }

    public static String JoinObject(String delimiter, Object wValues) {
        if (wValues == null)
            return "";

        return StringUtils.JoinCollection(delimiter, StringUtils.splitListObject(wValues, ","));
    }

    public static String JoinCollection(String delimiter, Collection wValues) {
        if (delimiter == null || wValues == null) {
            return "";
        }
        // Number of elements not likely worth Arrays.stream overhead.
        StringJoiner joiner = new StringJoiner(delimiter);
        for (Object cs : wValues) {
            joiner.add(cs.toString());
        }
        return joiner.toString();
    }


    public static String JoinArray(String delimiter, Object wValues) {
        if (delimiter == null || wValues == null) {
            return "";
        }

        if (!wValues.getClass().isArray()) {
            return "";
        }
        // Number of elements not likely worth Arrays.stream overhead.
        StringJoiner joiner = new StringJoiner(delimiter);
        int wLength = Array.getLength(wValues);

        for (int i = 0; i < wLength; i++) {
            joiner.add(Array.get(wValues, i).toString());
        }

        return joiner.toString();

    }

    public static String Join(String delimiter, Object... wValues) {
        if (delimiter == null || wValues == null) {
            return "";
        }
        // Number of elements not likely worth Arrays.stream overhead.
        StringJoiner joiner = new StringJoiner(delimiter);
        for (Object cs : wValues) {
            joiner.add(cs.toString());
        }
        return joiner.toString();

    }

//	public static  <T>  String Join(String delimiter, T... wValues) {
//		Objects.requireNonNull(delimiter);
//		Objects.requireNonNull(wValues);
//		// Number of elements not likely worth Arrays.stream overhead.
//		StringJoiner joiner = new StringJoiner(delimiter);
//		for (T cs : wValues) {
//			joiner.add(cs.toString());
//		}
//		return joiner.toString();
//
//	}

    public static int CompareDate(Calendar c1, Calendar c2) {
        String fmt = "yyyyMMdd";
        Calendar d1 = parseCalendar(parseCalendarToString(c1, fmt));
        Calendar d2 = parseCalendar(parseCalendarToString(c2, fmt));
        return d1.compareTo(d2);
    }

    public static int CompareCalendar(Calendar c1, Calendar c2, String fmt) {
        Calendar d1 = parseCalendar(parseCalendarToString(c1, fmt));
        Calendar d2 = parseCalendar(parseCalendarToString(c2, fmt));
        return d1.compareTo(d2);
    }

    public static int CompareTime(Calendar c1, Calendar c2) {
        String fmt = "HH:mm:ss";
        Calendar d1 = parseCalendar(parseCalendarToString(c1, fmt));
        Calendar d2 = parseCalendar(parseCalendarToString(c2, fmt));
        return d1.compareTo(d2);
    }

    public static String[] split(String wString, String wDelim) {
        return splitList(wString, wDelim).toArray(new String[0]);
    }


    public static String[] splitRegx(String wString, String wDelim) {
        return wString.split(wDelim);
    }

    public static List<String> splitListRegx(String wString, String wDelim) {
        return StringUtils.parseList(wString.split(wDelim));
    }

    public static List<String> splitListObject(Object wValues, String wDelim) {
        List<String> wResult = new ArrayList<>();
        if (wValues == null)
            return wResult;
        if (wValues instanceof Collection) {

            for (Object cs : (Collection) wValues) {
                wResult.add(cs.toString());
            }

        } else if (wValues.getClass().isArray()) {

            int wLength = Array.getLength(wValues);

            for (int i = 0; i < wLength; i++) {
                wResult.add(Array.get(wValues, i).toString());
            }
        } else {
            wResult = StringUtils.splitList(StringUtils.parseString(wValues), wDelim);
        }
        return wResult;
    }

    public static List<String> splitList(String wString, String wDelim) {
        List<String> wResult = new ArrayList<String>();
        try {
            if (wString == null || wString.length() <= 0) {
                return wResult;
            }

            if (wDelim != null && wDelim.length() > 1) {
                wDelim = wDelim.replaceAll("\\\\", "\\\\\\\\");
                wDelim = wDelim.replaceAll("\\+", "\\\\+");
                wDelim = wDelim.replaceAll("\\|", "\\\\|");
                wDelim = wDelim.replaceAll("\\*", "\\\\*");
                wDelim = wDelim.replaceAll("\\^", "\\\\^");
                wDelim = wDelim.replaceAll("\\$", "\\\\$");
                wDelim = wDelim.replaceAll("\\/", "\\\\/");
                wDelim = wDelim.replaceAll("\\[", "\\\\[");
                wDelim = wDelim.replaceAll("\\]", "\\\\]");
                wDelim = wDelim.replaceAll("\\(", "\\\\(");
                wDelim = wDelim.replaceAll("\\)", "\\\\)");
                wDelim = wDelim.replaceAll("\\-", "\\\\-");
                wDelim = wDelim.replaceAll("\\.", "\\\\.");

                wResult = StringUtils.parseList(wString.split(wDelim));
                return wResult;
            }
            StringTokenizer wStringTokenizer = new StringTokenizer(wString, wDelim);

            while (wStringTokenizer.hasMoreElements()) {
                wResult.add(wStringTokenizer.nextToken());
            }
        } catch (Exception e) {
            wResult.clear();
            wResult.add(wString);
            logger.error(e.toString());
        }
        return wResult;
    }


    public static List<String> splitList(String wString, String wDelim, boolean wNotEmpty) {

        List<String> wResult = splitList(wString, wDelim);
        if (wNotEmpty) {
            wResult.removeIf(p -> StringUtils.isEmpty(p));
        }

        return wResult;
    }

    public static List<String> splitStringList(Object wString, String wDelim) {

        return splitList(parseString(wString), wDelim);
    }

    public static List<Double> parseDoubleList(String wString, String wDelim) {

        return parseDoubleList(split(wString, wDelim));
    }

    public static List<Double> parseDoubleList(Object wString, String wDelim) {

        return parseDoubleList(split(parseString(wString), wDelim));
    }

    public static Double[] parseDoubleArray(String wString, String wDelim) {

        return parseDoubleList(split(wString, wDelim)).toArray(new Double[0]);
    }

    public static List<Integer> parseIntList(String wString, String wDelim) {

        return parseIntList(splitList(wString, wDelim));
    }

    public static List<Integer> parseIntList(Object wString, String wDelim) {

        return parseIntList(splitList(parseString(wString), wDelim));
    }

    public static String Format(String pattern, Object... arguments) {
        String wResult = pattern;
        try {

            if (arguments == null || arguments.length < 1) {
                return wResult;
            }

            int wLength = arguments.length;
            for (int i = 0; i < wLength; i++) {
                arguments[i] = String.valueOf(arguments[i]);
            }

            wResult = MessageFormat.format(pattern, arguments);
        } catch (Exception e) {
            logger.error(e.toString());
        }
        return wResult;
    }

    public static String LikeStrings(String wValue) {
        if (wValue == null || wValue.trim().length() <= 0) {
            return "";
        } else {
            return "%" + wValue.trim() + "%";
        }
    }

    /**
     * 将简单类型已格式化形式排列成字符串
     *
     * @param wMap
     * @return
     */
    public static String MapToString(Map<Integer, Integer> wMap) {
        List<String> wResult = new ArrayList<String>();

        for (Integer wT1 : wMap.keySet()) {
            if (wT1 == null) {
                continue;
            }
            if (wMap.get(wT1) == null) {
                continue;
            }

            wResult.add(StringUtils.Format("{0}+|:|+{1}", wT1, wMap.get(wT1)));
        }
        return StringUtils.Join("+|;|+", wResult);
    }

    /**
     * 将简单类型已格式化形式排列成字符串
     *
     * @return
     */
    public static <T1, T2> Map<T1, T2> StringToMap(String wMapString, Class<T1> wT1, Class<T2> wT2) {
        Map<T1, T2> wResult = new HashMap<T1, T2>();

        if (wMapString == null || wT1 == null || wT2 == null) {
            return wResult;
        }
        String[] wItemArray = null;
        for (String wItem : split(wMapString, "+|;|+")) {
            wItemArray = split(wItem, "+|:|+");
            if (wItemArray == null || wItemArray.length != 2) {
                continue;
            }

            wResult.put(ParseSimple(wItemArray[0], wT1), ParseSimple(wItemArray[1], wT2));
        }
        return wResult;
    }

    /**
     * 将某个值转为简单类型 仅支持： Integer Long Double Float Short String Byte Boolean
     *
     * @param wValue
     * @param wClazz
     * @return
     */
    @SuppressWarnings("unchecked")
    public static <T> T ParseSimple(Object wValue, Class<T> wClazz) {

        try {
            if (wValue == null || wClazz == null) {
                return null;
            }

            switch (wClazz.getSimpleName()) {
                case "Integer":
                    return (T) parseInt(wValue);
                case "Long":
                    return (T) parseLong(wValue);
                case "Double":
                    return (T) parseDouble(wValue);
                case "Float":
                    return (T) parseFloat(wValue);
                case "Short":
                    return (T) parseShort(wValue);
                case "String":
                    return (T) parseString(wValue);
                case "Byte":
                    return (T) parseByte(wValue);
                case "Boolean":
                    return (T) parseBoolean(wValue);
                default:
                    return wClazz.newInstance();
            }

        } catch (Exception e) {
            logger.error(e.getMessage());
        }
        return null;
    }

    public static String ParseToSql(Object wValue) {

        try {
            if (wValue == null) {
                return "";
            }

            switch (wValue.getClass().getSimpleName()) {
                case "Integer":
                case "Long":
                case "Double":
                case "Float":
                case "Short":
                case "Byte":
                case "Boolean":
                    return wValue.toString();
                case "String":
                    return "''" + wValue.toString() + "''";
                case "Calendar":
                    return "''" + parseCalendarToString((Calendar) wValue, "yyyy/MM/dd HH:mm:ss") + "''";
                case "Date":
                    return "''" + parseDateToString((Date) wValue, "yyyy/MM/dd HH:mm:ss") + "''";

                default:
                    return "''" + StringUtils.toJSONString(wValue) + "''";
            }

        } catch (Exception e) {
            logger.error(e.getMessage());
        }
        return "";
    }


    /**
     * 判断值类型 是否为空判断
     * 数字！=-1  字符串不能为空 时间不能小于2020年
     */
    public static boolean IsNotEmptyValue(Object wValue, String wTypeName) {
        return IsNotEmptyValue(wValue, wTypeName, -1, -1);
    }

    /**
     * 判断值类型 是否为空判断
     * 数字！=-1  字符串不能为空 时间不能小于2020年
     */
    public static boolean IsNotEmptyValue(Object wValue, String wTypeName, int wMinEmptyValue, int wMaxEmptyValue) {

        boolean result;
        if (wValue == null)
            return false;

        result = StringUtils.isNotEmpty(StringUtils.parseString(wValue));

        if (wValue instanceof Array) {
            if (Array.getLength(wValue) == 0)
                return false;
        }

        if (wValue instanceof Collection) {
            if (((Collection) wValue).size() == 0)
                return false;
        }

        if (result == false)
            return false;

        switch (wTypeName.toLowerCase()) {

            case "int":
            case "integer":
            case "short":
            case "boolean":
                result =
                        ((StringUtils.parseInt(wValue) > wMaxEmptyValue) || (StringUtils.parseInt(wValue) < wMinEmptyValue));
                break;
            case "long":
                result =
                        ((StringUtils.parseLong(wValue) > wMaxEmptyValue) || (StringUtils.parseLong(wValue) < wMinEmptyValue));
                //StringUtils.parseLong(wValue) != wEmptyValue;
                break;

            case "double":
                result =
                        ((StringUtils.parseDouble(wValue) > wMaxEmptyValue) || (StringUtils.parseDouble(wValue) < wMinEmptyValue));
                //StringUtils.parseDouble(wValue) != wEmptyValue;
                break;
            case "float":
                result =
                        ((StringUtils.parseFloat(wValue) > wMaxEmptyValue) || (StringUtils.parseFloat(wValue) < wMinEmptyValue));
                //StringUtils.parseFloat(wValue) != wEmptyValue;
                break;

            case "byte":
                result =
                        ((StringUtils.parseByte(wValue) > wMaxEmptyValue) || (StringUtils.parseByte(wValue) < wMinEmptyValue));
                //StringUtils.parseByte(wValue) != wEmptyValue;
                break;
            case "calendar":
            case "date":
                result = (StringUtils.parseCalendar(wValue).compareTo(CalendarTool.getUsedDate()) > 0);
                break;
            case "string":
            case "char":
            case "character":
            default:
                result = StringUtils.isNotEmpty(StringUtils.parseString(wValue));
                break;
        }
        return result;
    }


    public static String PadLeft(Object wValue, int wLength, char wChar) {

        String wValueStr = parseString(wValue);
        int wLth = wValueStr.length();
        while (wLth < wLength) {
            wValueStr = wChar + wValueStr;
            wLth++;
        }
        return wValueStr;
    }

    public static String PadRight(Object wValue, int wLength, char wChar) {
        String wValueStr = parseString(wValue);
        int wLth = wValueStr.length();
        while (wLth < wLength) {
            wValueStr = wValueStr + wChar;
            wLth++;
        }
        return wValueStr;
    }

    /**
     * 四舍五入
     */
    public static float numberHalfUp(float wValue, int wScale) {
        float wResult = 0f;
        try {
            String s = parseString(wValue);
            if (s.contains(".")) {
                String s1 = s.split("\\.")[1];
                if (s1.length() > wScale) {
                    wResult = new BigDecimal(wValue)
                            .setScale(wScale, RoundingMode.HALF_UP).floatValue();
                } else {
                    wResult = wValue;
                }
            } else {
                wResult = wValue;
            }
        } catch (Exception ex) {
            logger.error("numberHalfUp", ex);
        }
        return wResult;
    }
}



